package com.zhuangjie.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhaungjie.base.utils.PropertiesCopyUtils.PropertiesCopy;
import com.zhuangjie.security.intercepor.UserRequestInterceptor;
import com.zhuangjie.shop.constant.DishConstant;
import com.zhuangjie.shop.dto.DishPageWrapperPageDTO;
import com.zhuangjie.shop.dto.DishSaveDTO;
import com.zhuangjie.shop.entity.Dish;
import com.zhuangjie.shop.entity.DishFlavor;
import com.zhuangjie.shop.enums.DishBetterDisplayStatus;
import com.zhuangjie.shop.enums.DishStatus;
import com.zhuangjie.shop.helper.ShopModuleTokenDataProvider;
import com.zhuangjie.shop.mapper.DishMapper;
import com.zhuangjie.shop.service.DishFlavorService;
import com.zhuangjie.shop.service.DishService;
import com.zhuangjie.shop.vo.DishForCartItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜品表 服务实现类
 * </p>
 *
 * @author zhuangjie
 * @since 2023-09-24
 */
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private UserRequestInterceptor userRequestInterceptor;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Override
    public Page<Dish> queryShopCategoryListPage(Long shopId, DishPageWrapperPageDTO dishPageWrapperPageDTO) throws Exception {
        if (shopId == null && ( userRequestInterceptor.tryMountCurrentMountLoginState() == null || (shopId = ShopModuleTokenDataProvider.getShopId()) == null )) {
            // 该接口是用户端与商家端都会调用这个接口，如果是商家调用由于这是开发的接口还需要手动挂载登录信息来获取关联的shopId
            // 获取不到，报错
            throw new RuntimeException("获取菜品列表失败，无法获取店铺id！");
        }
        String query = dishPageWrapperPageDTO.getKeyword();
        // 组装搜索wrapper
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper();
        if (StringUtils.isNotBlank(query)) {
            query = query.trim();
            queryWrapper.like(Dish::getName,query);
        }
        // 只获取登录者对应店铺的分类信息
        queryWrapper.eq(Dish::getShopId,shopId);
        queryWrapper.eq(dishPageWrapperPageDTO.getDishCategoryId() != null, Dish::getDishCategoryId,dishPageWrapperPageDTO.getDishCategoryId());
        queryWrapper.eq(dishPageWrapperPageDTO.getDishStatus() != null, Dish::getStatus,dishPageWrapperPageDTO.getDishStatus());
        // 进行分页参数（currentPage,pageSize）+搜索参数（query）进行分页查询
        Page<Dish> page = this.page(new Page<>(dishPageWrapperPageDTO.getCurrentPage(), dishPageWrapperPageDTO.getPageSize()),queryWrapper);
        return page;
    }

    @Override
    public void changeDishStatus(Long dishId, Integer status) {
        // 获取店铺id，只能修改店铺下菜品的状态
        Long shopId = ShopModuleTokenDataProvider.getShopId();
        // 构造更新条件
        LambdaUpdateWrapper<Dish> changeDishStatusWrapper = Wrappers.lambdaUpdate(Dish.class)
                .set(Dish::getStatus, status)
                .eq(Dish::getShopId, shopId)
                .eq(Dish::getId, dishId);
        // 更新
        if (! this.update(changeDishStatusWrapper)) {
            throw new RuntimeException("更新失败！");
        }

    }

    @Override
    public void deleteBatchDishes(List<String> dishIds) {
        // 获取店铺id，只能删除店铺下菜品的状态
        Long shopId = ShopModuleTokenDataProvider.getShopId();
        // 构造条件
        LambdaQueryWrapper<Dish> deleteShopDishWrapper = Wrappers.lambdaQuery(Dish.class)
                .eq(Dish::getShopId, shopId)
                .in(Dish::getId, dishIds);
        // 删除
        if (this.baseMapper.delete(deleteShopDishWrapper) <= 0) {
            throw new RuntimeException("删除失败！");
        }
    }

    @Override
    @Transactional
    public void saveShopDish(DishSaveDTO dishSaveDTO) {
        Dish dish = PropertiesCopy.type(DishSaveDTO.class, Dish.class).produce(dishSaveDTO);
        Long shopId = ShopModuleTokenDataProvider.getShopId();
        // 自动填充商家id
        if (dishSaveDTO.getId() == null) {
            // 为新增菜品添加店铺id
            dish.setShopId(shopId);
            // 插入
            dish.setStatus(DishStatus.START_SALE.getValue());
            // 保存菜品数据
            this.baseMapper.insert(dish);
            if (dish.getId() == null) {
                throw new RuntimeException("插入菜品数据失败！");
            }
        }else {
            // 更新
            LambdaUpdateWrapper<Dish> dishLambdaUpdateWrapper = Wrappers.lambdaUpdate(Dish.class)
                    .eq(Dish::getShopId, shopId)
                    .eq(Dish::getId,dish.getId());
            int updateCount = this.baseMapper.update(dish, dishLambdaUpdateWrapper);
            // 删除原有口味项(如果更新失败了，我不确定你传入的菜品是否为你店铺的菜品，如果不作判断就会造成菜品口味的误删)
            if (updateCount == 0 && ! isShopDish(shopId,dish.getId())) {
                throw new RuntimeException("更新失败，菜品id非法");
            }
            LambdaQueryWrapper<DishFlavor> deleteDishFlavorWrapper = Wrappers.lambdaQuery(DishFlavor.class)
                    .eq(DishFlavor::getDishId, dish.getId());
            dishFlavorService.remove(deleteDishFlavorWrapper);
        }
        List<DishFlavor> flavors = dishSaveDTO.getFlavors();
        if (flavors != null && flavors.size() > 0) {
            // 保存口味数据
            // 为口味数据设置dishId
            flavors.forEach(flavor->{
                flavor.setDishId(dish.getId());
                // 添加不能存在id，flavor对象中id前端可能会传入
                flavor.setId(null);
            });
            dishFlavorService.saveBatch(flavors);
        }

    }

    @Override
    public DishSaveDTO getShopDishInfoById(Long dishId) {
        LambdaQueryWrapper<Dish> queryShopDishWrapper = Wrappers.lambdaQuery(Dish.class)
                .eq(Dish::getShopId, ShopModuleTokenDataProvider.getShopId())
                .eq(Dish::getId, dishId);
        Dish dish = this.baseMapper.selectOne(queryShopDishWrapper);
        if (dish == null) {
            return null;
        }
        // 如果dish不为空，查询其菜品口味信息
        LambdaQueryWrapper<DishFlavor> queryDishFlavorListWrapper = Wrappers.lambdaQuery(DishFlavor.class)
                .eq(DishFlavor::getDishId, dishId);

        List<DishFlavor> flavors = dishFlavorService.list(queryDishFlavorListWrapper);
        DishSaveDTO dishSaveDTO = PropertiesCopy.type(Dish.class, DishSaveDTO.class).produce(dish);
        dishSaveDTO.setFlavors(flavors);
        return dishSaveDTO;
    }

    @Override
    public void changeBetterDisplayStatus(Long dishId, Integer betterDisplayStatus) {
        // 查询优先展示的菜品id
        LambdaQueryWrapper<Dish> queryPriorityDisplayedDishIds = Wrappers.lambdaQuery(Dish.class)
                .eq(Dish::getShopId, ShopModuleTokenDataProvider.getShopId())
                .eq(Dish::getBetterDisplay, DishBetterDisplayStatus.OPEN.getValue())
                .select(Dish::getId);

        List<Dish> dishList = this.list(queryPriorityDisplayedDishIds);
        // 店铺中已经优先展示的菜品id
        List<Long> priorityDisplayedDishIds = dishList == null?new ArrayList<>():dishList.stream().map(dish -> dish.getId()).collect(Collectors.toList());
        Boolean isPriorityDisplayed = priorityDisplayedDishIds.contains(dishId);
        Boolean isCurrentOpen = Objects.equals(betterDisplayStatus,DishBetterDisplayStatus.OPEN.getValue()) ;
        // 判断是否不需要修改
        if(isPriorityDisplayed == isCurrentOpen) return;
        // 数量限制检查 (当原先关闭，现在打开时)
        if(! isPriorityDisplayed && isCurrentOpen) {
            priorityDisplayedDishIds.add(dishId);
            if (priorityDisplayedDishIds.size() > DishConstant.MAX_PRIORITY_DISPLAY_COUNT) {
                throw new RuntimeException("超过优先展示最大个数！");
            }
        }
        // 修改状态
        LambdaUpdateWrapper<Dish> updateBetterDisplayStatusUpdateWrapper = Wrappers.lambdaUpdate(Dish.class)
                .eq(Dish::getId, dishId)
                .set(Dish::getBetterDisplay, betterDisplayStatus);
        if(! this.update(updateBetterDisplayStatusUpdateWrapper)) {
            throw new RuntimeException("修改失败！");
        }
    }

    @Override
    public DishForCartItem getOneDishForCartItem(Long id) {
        if (id == null) return null;
        return this.baseMapper.getOneDishForCartItem(id);
    }

    @Override
    public Map<Long, String> queryDishCategoryNameByIds(List<Long> dishIdList) {
        LambdaQueryWrapper<Dish> queryDishWrapper = Wrappers.lambdaQuery(Dish.class)
                .eq(Dish::getShopId, ShopModuleTokenDataProvider.getShopId())
                .in(Dish::getId, dishIdList)
                .select(Dish::getId, Dish::getName);
        List<Dish> list = this.list(queryDishWrapper);
        if (list == null || list.isEmpty()) {
            throw new RuntimeException("无法查询到指定的菜品分类信息");
        }
        return list.stream().collect(Collectors.toMap(Dish::getId, Dish::getName));
    }

    /**
     * 商店菜
     *
     * @param dishId id
     * @param dishId
     * @return boolean
     */
    private boolean isShopDish(Long shopId, Long dishId) {
        LambdaQueryWrapper<Dish> selectShopDishWrapper = Wrappers.lambdaQuery(Dish.class)
                .eq(Dish::getShopId, shopId)
                .eq(Dish::getId, dishId);

        long count = this.count(selectShopDishWrapper);
        // count > 0 时可以从关联的店铺中找到菜品
        return count > 0;
    }

}
